package com.hotel.front;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.Util;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.labs.repackaged.org.json.JSONException;
import com.google.gson.Gson;
import com.hotel.BL.AgencyLogic;
import com.hotel.BL.ChargeLogic;
import com.hotel.BL.GenericLogic;
import com.hotel.BL.GuestLogic;
import com.hotel.BL.ReasonDetailLogic;
import com.hotel.BL.ReservationLogic;
import com.hotel.BL.RoomTypeLogic;
import com.hotel.BL.TaxLogic;

import data.Agency;
import data.Charge;
import data.Guest;
import data.Payment;
import data.ReasonDetail;
import data.Reservation;
import data.ReservationStatus;
import data.RoomType;
import data.passingData.DetailChargeData;
import data.passingData.ResultData;

@SuppressWarnings("serial")
public class ChargeService extends HttpServlet {
	// http://localhost:8080/ChargeService?func=addCharge&title=1&Description=q&Percentcharge=true&fix=true&chargeDay=true&value=2&beforeCheckIn=2&charge=30&isDay=true
	// http://localhost:8080/ChargeService?func=editCharge&ChargeId=876&title=122222222222222&Description=q&Percentcharge=true&fix=true&chargeDay=true&value=2&beforeCheckIn=2&charge=30&isDay=true
	// http://localhost:8080/ChargeService?func=delCharge&ChargeId=878
	// http://localhost:8080/ChargeService?func=changeStatus&ChargeId=878
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		try {
			String doClass = req.getParameter("func");
			if (doClass.equals("addCharge")) {
				AddCharge(req, resp);
			}else if (doClass.equals("detailCharge")){
				DetailCharge(req, resp);
			}else if(doClass.equals("getCharge")){
				GetChargeGroup(req,resp);
			}else if(doClass.equals("editRefund")){
				EditRefund(req,resp);
			}else if(doClass.equals("ExceptTex")){
				ExceptTex(req,resp);
			}
//				else if(doClass.equals("testCalCharge")){
//				testCalCharge(req, resp);
//			}
			/*if(doClass.equals("editFolioInCharge")){
				EditFolioinCharge(req,resp);
			}*/
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void AddCharge(HttpServletRequest req, HttpServletResponse resp)
			throws IOException, JSONException, ServletException,
			EntityNotFoundException, ParseException {
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm",
				Locale.ENGLISH);
		long hotelId = (Long) session.getAttribute("hotelId");
		String description = (String) req.getParameter("description");
		String chargeAmount = req.getParameter("chargeAmount");
		long chargeQty = Long.parseLong(req.getParameter("chargeQty"));
		Date chargeDate = formatter.parse((String) req
				.getParameter("chargeDate"));
		double discount = Double.parseDouble((String) req
				.getParameter("discount"));
		String subFolio = (String) req.getParameter("subFolio");
		Boolean isLock = Boolean.parseBoolean(req.getParameter("isLock"));
		String resId = req.getParameter("resId");
		String type = req.getParameter("type");
		Boolean isRoomCharge = Boolean.parseBoolean(req
				.getParameter("isRoomCharge"));
		String reasonString = req.getParameter("reason");
		String emailMassage = req.getParameter("massage");
		String chargeType   = req.getParameter("chargeType");
		String resStatus = req.getParameter("resStatus");
		
		long groupId =0;
		long rsId=0;
		if(req.getParameter("groupId")!=null){
			groupId = Long.parseLong(req.getParameter("groupId"));
		}
		boolean sellRoom = false;
		if(req.getParameter("sellRoom") != null){
			sellRoom = Boolean.parseBoolean(req.getParameter("sellRoom"));
		}
		boolean isAssign = false;
		if(req.getParameter("isAssign") != null){
			isAssign = Boolean.parseBoolean(req.getParameter("isAssign"));
		}
		List<Charge> list = new ArrayList<Charge>();
		if(resId.equals("0")){
			String roomId = req.getParameter("rmId");
			String roomType = req.getParameter("rmType");
			long roomAmount = Long.parseLong(req.getParameter("roomamount"));
			String priceRateId = req.getParameter("priceRate");
			long adult = Long.parseLong(req.getParameter("adult"));
			long child = Long.parseLong(req.getParameter("child"));
			GenericLogic generalLogic = new GenericLogic(req,resp);
			ReservationStatus rsv = generalLogic.GetReservationStatus(hotelId,
					resStatus);

			long salutatinId = Long.parseLong(req.getParameter("sal"));
			String name = req.getParameter("nm");
			String lastName = req.getParameter("lsNm");
			String phone = req.getParameter("phone");
			String mail = req.getParameter("mail");
			Double pay = Double.parseDouble(req.getParameter("pay"));
			String guestnamelist = req.getParameter("arrayguestname");
			String guestsolutationlist = req.getParameter("arrayguestsolutation");
			String guestlastnamelist = req.getParameter("arrayguestlastname");
			String guestphonelist = req.getParameter("arrayguestphone");
			String guestemaillist = req.getParameter("arrayguestemail");
			long span = Long.parseLong(req.getParameter("span"));
			String sources = "";
			String reason  = "";
			long extrabed   = 0;
			RoomTypeLogic rmLogic = new RoomTypeLogic(req,resp);
			RoomType rmData = rmLogic.GetRoomType(Long.parseLong(roomType));
			if ((child + adult) - (long) rmData.getStandardOccupancy() >= 0) {
				extrabed = (child + adult) - rmData.getStandardOccupancy();
			} else {
				extrabed = 0;
			}
			String reservationStatus  = Long.toString(rsv.getId());
			Guest gs =new GuestLogic(req,resp).AddGuest(salutatinId, name, lastName,
					phone,  mail);
			String agencyId = "";
			if (req.getParameter("agencyId").equals("0")) {
				AgencyLogic aLogic = new AgencyLogic(req,resp);
				long displayID = aLogic.GetMaxAgentDisplayId(hotelId);
				Agency agent = aLogic.AddAgency(hotelId,
						req.getParameter("agency"), "",(displayID+1));
				agencyId = String.valueOf(agent.getId());
			} else {
				agencyId = req.getParameter("agencyId");
			}
			Reservation rse = new ReservationLogic(req,resp).CreateReservation(
					hotelId, chargeDate, span, roomId, roomType, priceRateId,
					adult, child, isAssign, String.valueOf(gs.getId()),
					reservationStatus, roomAmount, sources,
					extrabed, reason, agencyId, pay,guestnamelist,guestsolutationlist,
					guestlastnamelist,guestphonelist,guestemaillist);
			resId = String.valueOf(rse.getId());
		}
		String[] resAry = resId.trim().split(",");
		String[] chargeAmountAry = chargeAmount.trim().split(",");
		Charge obj  = new Charge();
		ReservationLogic rLogic = new ReservationLogic(req,resp);
		ChargeLogic chargeLogic = new ChargeLogic(req,resp);
		ReasonDetail rd = new ReasonDetail();
		if(groupId != 0)
		{
			for(int i=0;i<resAry .length;i++){
				if(obj != null&&resStatus!=null)
				{
					chargeLogic.ChangeResStatus(hotelId,resAry[i], resStatus, isAssign, sellRoom);
				}
				if(reasonString!=null){
				rd = new ReasonDetailLogic().AddReasonDetail(hotelId, String.valueOf(groupId), reasonString, description, chargeDate, emailMassage);
				rsId = rd.getId();
				}
				double chargeofPrice =0;
				double taxofPrice =0;
				if(chargeType!=null){
					HashMap<String,Double> calTax=new TaxLogic(req,resp).CalRoomTaxWithPolicy(hotelId, Double.parseDouble(chargeAmount), false);
					 chargeofPrice =calTax.get("costIncludeTax");
					 taxofPrice =calTax.get("tax");
				}else{
					chargeofPrice =Double.parseDouble(chargeAmount)+Double.parseDouble(chargeAmount)*0.07;
					taxofPrice = Double.parseDouble(chargeAmount)*0.07;
				}
				obj = chargeLogic.AddCharge(hotelId, description,chargeQty,
						chargeofPrice, chargeDate, discount, subFolio,taxofPrice,
						isLock, isRoomCharge,false,rsId,emailMassage,chargeType);
				
			}
			rLogic.EditChargeGroup(hotelId, Long.parseLong(resId), String.valueOf(obj.getId()),obj.isRoomCharge());
			list.add(obj);
		}
		else{
			StringBuilder builder = new StringBuilder();
			for(String s : resAry) {
			    builder.append(s);
			}
			if(reasonString!=null){
				rd = new ReasonDetailLogic().AddReasonDetail(hotelId, builder.toString(), reasonString, description, chargeDate, emailMassage);
				rsId = rd.getId();
				}
			for(int i=0;i<resAry .length;i++){
				double chargeofPrice =0;
				double taxofPrice =0;
				if(chargeType!=null){
					HashMap<String,Double> calTax=new TaxLogic(req,resp).CalRoomTaxWithPolicy(hotelId, Double.parseDouble(chargeAmountAry[i]), false);
					 chargeofPrice =calTax.get("costIncludeTax");
					 taxofPrice =calTax.get("tax");
				}else{
					chargeofPrice =Double.parseDouble(chargeAmountAry[i])+Double.parseDouble(chargeAmountAry[i])*0.07;
					taxofPrice = Double.parseDouble(chargeAmountAry[i])*0.07;
				}
				obj = chargeLogic.AddCharge(hotelId, description,chargeQty,
						chargeofPrice, chargeDate, discount, subFolio,taxofPrice,
				isLock, isRoomCharge,false,rsId,emailMassage,chargeType);
				if(obj != null&&resStatus!=null)
				{
					chargeLogic.ChangeResStatus(hotelId,resAry[i], resStatus, isAssign, sellRoom);
				}
				if(type.equals("Single")){
	
					rLogic.EditReservationCharge(hotelId,Long.parseLong(resAry[i]),String.valueOf(obj.getId()),obj.isRoomCharge());
				}
				list.add(obj);
			}
		}
		if(list.size()!=0){
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(list));
		}
	}
	private void GetChargeGroup(HttpServletRequest req, HttpServletResponse resp)
			throws ParseException, IOException, EntityNotFoundException {
		
		String chargeId = req.getParameter("chargeId");
		List<Charge> list = new ArrayList<Charge>();
		if(chargeId == null ||chargeId.equals(""))
		{
			list=null;
		}else{
		String [] chargeArray = chargeId.trim().split(",");
		
		for(int i=0;i<chargeArray.length;i++){
		Charge g = new ChargeLogic(req,resp).GetCharge(Long.parseLong(chargeArray[i]));
		list.add(g);
		}
		}
		Gson gson = new Gson();

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(list));
	}
	
	private void DetailCharge(HttpServletRequest req, HttpServletResponse resp)
			throws IOException, JSONException, ServletException,
			EntityNotFoundException, ParseException {
		
		HttpSession session = req.getSession(true);
		long hotelId = (Long) session.getAttribute("hotelId");
		long groupId = Long.parseLong(req.getParameter("groupId"));
		long resId = Long.parseLong(req.getParameter("resId"));
		double roomCharge = 0;
		double otherCharge =  0;
		double tax =  0;
		double otherDiscount = 0;
		double totalCharge = 0;
		double pay =  0;
		double balance =   0;
		double roomDiscount = 0;
		if(groupId != 0){
			ReservationLogic rLogic = new ReservationLogic(req,resp); 
			List<Reservation> resList = rLogic.GetGroup(groupId).getListResv();				
			//list Charge in group
			List<Charge> listChargeG = null;
			if(rLogic.GetGroup(groupId).getChargeListString()!=null){ //pao edit
				listChargeG = rLogic.GetGroup(groupId).getChargeList();
				if(listChargeG !=null){
					for(int j = 0; j<listChargeG.size(); j++){
						if(!listChargeG.get(j).isRefund() && !listChargeG.get(j).isTemp()){
							if(listChargeG.get(j).isRoomCharge() ){
								roomCharge += listChargeG.get(j).getChargeAmount();
								roomDiscount += listChargeG.get(j).getDiscount();
							}else{
								otherCharge += listChargeG.get(j).getChargeAmount();
								otherDiscount += listChargeG.get(j).getDiscount();
							}	
						}
						tax += new TaxLogic(req,resp).CalTax(hotelId, listChargeG.get(j).getChargeAmount());
						
					}
				}
			}
				//list Payment in group
				List<Payment> listPaymentG = rLogic.GetGroup(groupId).getPaymentList();
				if(listPaymentG != null){
					for(int j = 0; j<listPaymentG.size(); j++){
						pay += listPaymentG.get(j).getAmount();
					}
				}
				TaxLogic taxLogic = new TaxLogic(req,resp);
				//list Reservation
				for(int y = 0;y<resList.size();y++){
					List<Charge> chargeList = resList.get(y).getChargeList();
					//list Charge
					if(chargeList != null){
						for(int i = 0 ; i<chargeList.size();i++){
							if(!chargeList.get(i).isRefund() && !chargeList.get(i).isTemp()){
								if(chargeList.get(i).isRoomCharge()){
									roomCharge += chargeList.get(i).getChargeAmount();
								}else{
										otherCharge += listChargeG.get(i).getChargeAmount();
										otherDiscount += listChargeG.get(i).getDiscount();
								}
								tax += taxLogic.CalTax(hotelId, chargeList.get(i).getChargeAmount());
							}
						}					
					}
					List<Payment> listPayment = rLogic.GetReservation(resId).getPaymentList();
					if(listPayment != null){
						for(int j = 0; j<listPayment.size(); j++){
							pay += listPayment.get(j).getAmount();
						}
					}			
				}
				totalCharge = roomCharge + otherCharge + tax + otherCharge;
				balance = totalCharge - pay ;
			
		}else{
			ReservationLogic rLogic = new ReservationLogic(req,resp);
			List<Charge> listCharge = rLogic.GetReservation(resId).getChargeList();
			TaxLogic taxLogic = new TaxLogic(req,resp);
			for(int i = 0 ; i<listCharge.size();i++){
				if(!listCharge.get(i).isRefund() && !listCharge.get(i).isTemp()){
					if(listCharge.get(i).isRoomCharge() == true){
						roomCharge += listCharge.get(i).getChargeAmount();
						roomDiscount += listCharge.get(i).getDiscount();
					}else{
						otherCharge += listCharge.get(i).getChargeAmount();
						otherDiscount += listCharge.get(i).getDiscount();
					}
					tax += taxLogic.CalTax(hotelId, listCharge.get(i).getChargeAmount());
				}
			}

			totalCharge = tax + otherCharge + roomCharge /*- otherDiscount - roomDiscount*/;
			
			List<Payment> listPayment = rLogic.GetReservation(resId).getPaymentList();
			if(listPayment != null){
				for(int j = 0; j<listPayment.size(); j++){
					pay += listPayment.get(j).getAmount();
				}
			}
			balance = totalCharge - pay ;
			
		}
		DetailChargeData detail = new DetailChargeData();
		detail.setBalance(balance);
		detail.setOtherCharge(otherCharge);
		detail.setPay(pay);
		detail.setRoomCharge(roomCharge);
		detail.setTax(tax);
		detail.setOtherDiscount(otherDiscount);
		detail.setTotalCharge(totalCharge);
		detail.setRoomDiscount(roomDiscount);
		
		Gson gson = new Gson();

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(detail));
	}
	
	private void EditRefund(HttpServletRequest req, HttpServletResponse resp)
		throws ParseException, IOException, EntityNotFoundException {
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		String chargeIdList = req.getParameter("chargeIdArray");
		List<Charge> list = new ArrayList<Charge>();
		Charge g = new Charge();
		ChargeLogic chargeLogic = new ChargeLogic(req,resp);
		for(int i = 0;i<chargeIdList.split(",").length;i++){
		g = chargeLogic.EditRefund(Long.parseLong(chargeIdList.split(",")[i]));
		list.add(g);
		}
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(list));
	}
	/*private void EditFolioinCharge(HttpServletRequest req, HttpServletResponse resp)
			throws ParseException, IOException, EntityNotFoundException {

			long chargeId = Long.parseLong(req.getParameter("chargeId"));
			long folioId = Long.parseLong(req.getParameter("folioId"));
			String subFolioId = req.getParameter("subFolioId");
			Charge g = new Charge();
			g = new ChargeLogic().EditFolio(chargeId,folioId,subFolioId);
			Gson gson = new Gson();
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(g));
	}*/
	
	private void ExceptTex(HttpServletRequest req, HttpServletResponse resp)
			throws ParseException, IOException, EntityNotFoundException {
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		String chargeIdList = req.getParameter("chargeId").trim();
		boolean g = new ChargeLogic(req,resp).ExceptTex(chargeIdList);
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(g));
	}
	
}
